#pragma once
#include "zMatrixBase.hpp"

namespace zzz{
//func(v,mat)
#define CONSTANT_LEFT_EXPRESSIONC(name,func) \
template<typename T,class Major>\
class zFunctionLeft##name##ExpressionC : public zMatrixBaseR<T,Major>\
{\
public:\
  explicit zFunctionLeft##name##ExpressionC(const T &v, const zMatrixBaseR<T,Major>& mat)\
  :zMatrixBaseR<T,Major>(mat.rows_,mat.cols_),Mat_(mat),v_(v){}\
  using zMatrixBaseR<T,Major>::operator(); \
  const T operator()(zuint r, zuint c) const\
  {\
    CheckRange(r, c); \
    return func(v_, Mat_(r,c)); \
  }\
private:\
  const T &v_; \
  const zMatrixBaseR<T,Major> &Mat_; \
};

CONSTANT_LEFT_EXPRESSIONC(Pow,Pow<T>)
template<typename T,class Major>
const zFunctionLeftPowExpressionC<T,Major> operator^(const T &value, const zMatrixBaseR<T,Major> &mat)
{return zFunctionLeftPowExpressionC<T,Major>(value,mat);};

//func(mat,c)
#define CONSTANT_RIGHT_EXPRESSIONC(name,func) \
template<typename T,class Major>\
class zFunctionRight##name##ExpressionC : public zMatrixBaseR<T,Major>\
{\
public:\
  explicit zFunctionRight##name##ExpressionC(const zMatrixBaseR<T,Major>& mat,const T &v)\
  :zMatrixBaseR<T,Major>(mat.rows_,mat.cols_),Mat_(mat),v_(v){}\
  using zMatrixBaseR<T,Major>::operator(); \
  const T operator()(zuint r, zuint c) const\
  {\
    CheckRange(r, c); \
    return func(Mat_(r,c),v_); \
  }\
private:\
  const T &v_; \
  const zMatrixBaseR<T,Major> &Mat_; \
}; \

CONSTANT_RIGHT_EXPRESSIONC(Pow,Pow<T>)
template<typename T,class Major>
const zFunctionRightPowExpressionC<T,Major> operator^(const zMatrixBaseR<T,Major> &mat,const T &value)
{return zFunctionRightPowExpressionC<T,Major>(mat,value);};


}
